1. Field of the Invention
Embodiments of the present invention generally relate to secure sandboxes and, more particularly, to a method and apparatus for preventing an interrupt descriptor tables (IDT)-based security sandbox from causing a kernel panic when using a call gate.
2. Description of the Related Art
Secure execution of software applications is important in all computer systems. For example, errors in an application's code, in third party libraries and in an operating system, hereinafter referred to as “bugs”, can expose the application to a security attack. One or more applications executing on a computing system may need to securely execute identified untested or untrusted code. Thus, executing a thread (that is, a scheduled amount of processing by an operating system), to occur in a secure sandbox provided by a host (generally referred to as “sandboxing”), is one way to try to prevent untrusted code from performing malicious activities on the host. Sandboxing allows a thread to execute in a secure environment included in a computing system. For example, a computing system can enable and use a secure sandbox to execute the identified untested or untrusted code. The computing system executes the identified code separately from other code in order to prevent the identified code from performing unwanted or, in some cases, malicious tasks in the computing system. A client application running on a host computing system selectively sets up the secure sandbox and uses it to execute the identified code. The secure sandbox monitors the execution of the thread while providing a controlled set of resources for use by the thread. For example, a sandbox allows a client application to securely execute a thread that is running code downloaded from the Internet or third party libraries. In addition, an application that accesses and uses untrusted data can be potentially open to security attacks. The use of a sandbox isolates and prevents the security attacks from affecting a host computer system.
A processor uses an interrupt descriptor table (IDT) to decide what to do when an interrupt occurs. In situations where more than one IDT has been created, an IDT register (IDTR) is included in a host computing system to point to the current IDT, such as a standard or default IDT. Moreover, a device driver, including an application program interface (API) may modify the IDTR to instead point to another IDT, such as a custom IDT. The use of a custom IDT allows untrusted code to operate in a secure sandbox without having access to the operating system kernel. An IDT-based secure sandbox is created with the aid of the device driver. The device driver maps code (called the “epilog”) into the memory map of the thread to be sandboxed. The sandbox is then enabled by substituting a different IDT when the sandboxed thread is executing. This allows all interrupts to be intercepted by the device driver. Other kernel entry instructions, for example system call instructions (“syscall”) and system enter instructions (“sysenter”), may similarly be intercepted by the device driver. The stack is a data structure in memory. When an interrupt fires during execution of an application, the address in the application code where execution was interrupted is stored in the stack. When programming control needs to be transitioned to the kernel (for example, when processing a timer interrupt or a syscall/sysenter), the original IDT is restored, a return address on a stack is saved and replaced with the address of the epilog. Control is then passed to a kernel interrupt handler. When the kernel finishes handling the interrupt, it looks to the stack to see to what address it is to return control. After the kernel resumes execution of the thread that was sandboxed, the epilog code executes and calls the driver to re-enable the sandbox, which then replaces the return address in the stack so that programming control will resume at the point where the original interrupt (or syscall/sysenter) occurred. The IDT-based sandbox is enabled using a call gate to transition to driver-controlled code without going through the operating system kernel. However, when the call gate is used to transition to driver-controlled code, referred to as “jumping through the call gate”, the stack is switched from a low privilege stack to a high privilege stack. When an interrupt (or syscall/sysenter) occurs while the sandbox is enabled, the driver may decide to ignore or handle the interrupt itself, or possibly transfer control to the kernel to handle the interrupt (or syscall/sysenter).
An application is not able to disable interrupts before calling the call gate without the CPU privilege level being elevated to grant permission to the application. After jumping through the call gate, the thread will begin using a higher privilege stack (e.g., the ring 0 stack on an INTEL® x86 platform). However, for example, a timer event might fire causing a timer interrupt to be triggered after a jump through the call gate but before interrupts are disabled. In that case, the kernel would start executing the timer interrupt handler using the same high level privilege stack. If the timer interrupt handler makes assumptions about the contents of the stack, specifically, if the kernel assumes the stack was empty prior to the interrupt, that could cause a panic (an action taken by an operating system upon detecting an internal fatal error), which could cause the kernel to shut down. Alternatively, if the timer interrupt does not make assumptions about what is on the stack, but the handler happens to use what would normally be all of the available stack space, because additional values have been added onto the stack, it could end up overflowing the stack. Accordingly, because the high privilege level stack (ring 0 stack on an INTEL® x86 platform) is being used when jumping the call gate, if interrupts are not disabled to keep them from being handled by the kernel, there could be conflicts between how the kernel handles that interim stack and the way the application handles the interim stack.
Therefore, there is a need for a method and apparatus for preventing an IDT-based security sandbox from causing a kernel panic when using a call gate.